﻿using System;
using System.Threading;

namespace Sunny.Com;

/// <summary>
/// 值类型计数定时器(默认计数周期1秒，计数时间间隔需小于计数周期)
/// </summary>
internal struct ValueCountTimer
{
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="period">计数周期</param>
    public ValueCountTimer(TimeSpan period)
    {
        Period = period;
    }

    /// <summary>
    /// 构造函数，默认计数周期1秒
    /// </summary>
    public ValueCountTimer()
    {
        Period = TimeSpan.FromSeconds(1);
    }

    /// <summary>
    /// 周期内的累计计数值。
    /// </summary>
    private long _count;

    /// <summary>
    /// 最后一次递增时间
    /// </summary>
    private DateTime _lastAdded;

    /// <summary>
    /// 周期内的累计计数值。
    /// </summary>
    public readonly long Count => _count;

    /// <summary>
    /// 最后一次递增时间
    /// </summary>
    public readonly DateTime LastAdded => _lastAdded;

    /// <summary>
    /// 当达到一个周期时触发。
    /// </summary>
    public Action<long> Tick { get; set; }

    /// <summary>
    /// 计数周期，。
    /// </summary>
    public TimeSpan Period { get; set; }

    /// <summary>
    /// 累计增加计数
    /// </summary>
    /// <param name="value"></param>
    /// <returns>返回值表示当前递增的是否在一个周期内。</returns>
    public bool Add(long value = 1)
    {
        bool isPeriod;
        if (DateTime.Now - this.LastAdded > this.Period)
        {
            this.Tick?.Invoke(this._count);
            Interlocked.Exchange(ref this._count, 0);
            isPeriod = false;
            this._lastAdded = DateTime.Now;
        }
        else
        {
            isPeriod = true;
        }

        Interlocked.Add(ref this._count, value);
        return isPeriod;
    }

    /// <summary>
    /// 重置
    /// </summary>
    public void Reset()
    {
        this._count = 0;
        this._lastAdded = default;
    }
}